namespace Gj.Cache
{
    public class LFUDoubleLinkedList<K, V>
    {
        private readonly LFUNode<K, V> Head;
        private readonly LFUNode<K, V> Tail;

        public LFUDoubleLinkedList()
        {
            Head = new LFUNode<K, V>();
            Tail = new LFUNode<K, V>();
            Head.Next = Tail;
            Tail.Previous = Head;
            Count = 0;
        }

        public int Count { get; private set; }

        public void AddToTop(LFUNode<K, V> node)
        {
            node.Previous = Head;
            node.Next = Head.Next;
            node.Next.Previous = node;
            Head.Next = node;
            Count++;
        }

        public void RemoveNode(LFUNode<K, V> node)
        {
            node.Previous.Next = node.Next;
            node.Next.Previous = node.Previous;
            node.Previous = null;
            node.Next = null;
            Count--;
        }

        public LFUNode<K, V> RemoveLFUNode()
        {
            var target = Tail.Previous;
            RemoveNode(target);
            return target;
        }
    }
}